home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / sio.1.5.6 / sprint.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-09  |  16.2 KB  |  739 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7.  
  8. static char RCSid[] = "$Id: sprint.c,v 7.1 1992/06/01 21:58:01 panos Exp $" ;
  9.  
  10. #include <ctype.h>
  11.  
  12. #include "sio.h"
  13. #include "impl.h"
  14.  
  15. #define S_NULL                "(null)"
  16. #define S_NULL_LEN        6
  17.  
  18. #define FLOAT_DIGITS        6
  19.  
  20. #define EXPONENT_LENGTH                    10
  21.  
  22. /*
  23.  * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
  24.  */
  25. #define NUM_BUF_SIZE            512
  26.  
  27. /*
  28.  * The INS_CHAR macro inserts a character in the buffer and writes
  29.  * the buffer back to disk if necessary
  30.  * It uses the char pointers sp and bep:
  31.  * sp points to the next available character in the buffer and
  32.  * bep points to the end-of-buffer+1.
  33.  * While using this macro, note that the nextb pointer is NOT updated.
  34.  *
  35.  * No I/O is performed if fd is not positive. Negative fd values imply
  36.  * conversion with the output directed to a string. Excess characters
  37.  * are discarded if the buffer overflows.
  38.  *
  39.  * NOTE: Evaluation of the c argument should not have any side-effects
  40.  */
  41. #define INS_CHAR( c, sp, bep, odp, cc, fd )                                            \
  42.             {                                                                                        \
  43.                 if ( sp < bep )                                                                \
  44.                     *sp++ = c ;                                                                    \
  45.                 else                                                                                \
  46.                 {                                                                                    \
  47.                     if ( fd >= 0 )                                                                \
  48.                     {                                                                                \
  49.                         odp->nextb = sp ;                                                        \
  50.                         if ( __sio_writef( odp, fd ) != bep - odp->start )            \
  51.                             return( ( cc != 0 ) ? cc : SIO_ERR ) ;                        \
  52.                         sp = odp->nextb ;                                                        \
  53.                     }                                                                                \
  54.                     *sp++ = c ;                                                                    \
  55.                 }                                                                                    \
  56.                 cc++ ;                                                                            \
  57.                 if ( __SIO_MUST_FLUSH( *odp, c ) && fd >= 0 )                         \
  58.                 {                                                                                    \
  59.                     int b_in_buffer = sp - odp->start ;                                    \
  60.                                                                                                     \
  61.                     odp->nextb = sp ;                                                            \
  62.                     if ( __sio_writef( odp, fd ) != b_in_buffer )                    \
  63.                         return( cc ) ;                                                            \
  64.                     sp = odp->nextb ;                                                            \
  65.                 }                                                                                    \
  66.             }
  67.  
  68.  
  69.  
  70. #define NUM( c )            ( c - '0' )
  71.  
  72. #define STR_TO_DEC( str, num )                                    \
  73.                                     num = NUM( *str++ ) ;            \
  74.                                     while ( isdigit( *str ) )        \
  75.                                     {                                        \
  76.                                         num *= 10 ;                        \
  77.                                         num += NUM( *str++ ) ;        \
  78.                                     }
  79.  
  80. /*
  81.  * This macro does zero padding so that the precision
  82.  * requirement is satisfied. The padding is done by
  83.  * adding '0's to the left of the string that is going
  84.  * to be printed.
  85.  */
  86. #define FIX_PRECISION( adjust, precision, s, s_len )                \
  87.                     if ( adjust )                                                \
  88.                         while ( s_len < precision )                        \
  89.                         {                                                            \
  90.                             *--s = '0' ;                                        \
  91.                             s_len++ ;                                            \
  92.                         }
  93.  
  94. /*
  95.  * Macro that does padding. The padding is done by printing
  96.  * the character ch.
  97.  */
  98. #define PAD( width, len, ch )            do                                                        \
  99.                                                 {                                                        \
  100.                                                     INS_CHAR( ch, sp, bep, odp, cc, fd ) ;    \
  101.                                                     width-- ;                                        \
  102.                                                 }                                                        \
  103.                                                 while ( width > len )
  104.  
  105. /*
  106.  * Prefix the character ch to the string str
  107.  * Increase length
  108.  * Set the has_prefix flag
  109.  */
  110. #define PREFIX( str, length, ch )    *--str = ch ; length++ ; has_prefix = YES
  111.  
  112.  
  113. /*
  114.  * Sprint is the equivalent of printf for SIO.
  115.  * It returns the # of chars written
  116.  * Assumptions:
  117.  *     - all floating point arguments are passed as doubles
  118.  */
  119. /* VARARGS2 */
  120. int Sprint( fd, fmt, va_alist ) 
  121.     int fd ;
  122.     register char *fmt ;
  123.     va_dcl
  124. {
  125.     __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  126.     register __sio_od_t *odp = ODP( dp ) ;
  127.     register int cc ;
  128.     va_list ap ;
  129.  
  130.     IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  131.  
  132.     va_start( ap ) ;
  133.     cc = __sio_converter( odp, fd, fmt, ap ) ;
  134.     va_end( ap ) ;
  135.     return( cc ) ;
  136. }
  137.  
  138.  
  139. /*
  140.  * This is the equivalent of vfprintf for SIO
  141.  */
  142. int Sprintv( fd, fmt, ap )
  143.     int fd ;
  144.     char *fmt ;
  145.     va_list ap ;
  146. {
  147.     __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;
  148.     register __sio_od_t *odp = ODP( dp ) ;
  149.  
  150.     IO_SETUP( fd, dp, __SIO_OUTPUT_STREAM, SIO_ERR ) ;
  151.     return( __sio_converter( odp, fd, fmt, ap ) ) ;
  152. }
  153.  
  154.  
  155. /*
  156.  * Convert a floating point number to a string formats 'f', 'e' or 'E'.
  157.  * The result is placed in buf, and len denotes the length of the string
  158.  * The sign is returned in the is_negative argument (and is not placed
  159.  * in buf).
  160.  */
  161. PRIVATE char *conv_fp( format, num, add_dp, precision, is_negative, buf, len )
  162.     register char format ;
  163.     register double num ;
  164.     boolean_e add_dp ;            /* always add decimal point if YES */
  165.     int precision ;
  166.     int *is_negative ;
  167.     char buf[] ;
  168.     int *len ;
  169. {
  170.     register char *s = buf ;
  171.     register char *p ;
  172.     int decimal_point ;
  173.     char *ecvt(), *fcvt() ;
  174.     char *conv_10() ;
  175.     char *strcpy() ;
  176.         
  177.     if ( format == 'f' )
  178.         p = fcvt( num, precision, &decimal_point, is_negative ) ;
  179.     else /* either e or E format */
  180.         p = ecvt( num, precision+1, &decimal_point, is_negative ) ;
  181.  
  182.     /*
  183.      * Check for Infinity and NaN
  184.      */
  185.     if ( isalpha( *p ) )
  186.     {
  187.         *len = strlen( strcpy( buf, p ) ) ;
  188.         *is_negative = FALSE ;
  189.         return( buf ) ;
  190.     }
  191.     
  192.     if ( format == 'f' )
  193.         if ( decimal_point <= 0 )
  194.         {
  195.             *s++ = '0' ;
  196.             if ( precision > 0 )
  197.             {
  198.                 *s++ = '.' ;
  199.                 while ( decimal_point++ < 0 )
  200.                     *s++ = '0' ;
  201.             }
  202.             else if ( add_dp )
  203.                 *s++ = '.' ;
  204.         }
  205.         else
  206.         {
  207.             while ( decimal_point-- > 0 )
  208.                 *s++ = *p++ ;
  209.             if ( precision > 0 || add_dp ) *s++ = '.' ;
  210.         }
  211.     else
  212.     {
  213.         *s++ = *p++ ;
  214.         if ( precision > 0 || add_dp ) *s++ = '.' ;
  215.     }
  216.  
  217.     /*
  218.      * copy the rest of p, the NUL is NOT copied
  219.      */
  220.     while ( *p ) *s++ = *p++ ;            
  221.     
  222.     if ( format != 'f' )
  223.     {
  224.         char temp[ EXPONENT_LENGTH ] ;                /* for exponent conversion */
  225.         int t_len ;
  226.         int exponent_is_negative ;
  227.  
  228.         *s++ = format ;        /* either e or E */
  229.         decimal_point-- ;
  230.         if ( decimal_point != 0 )
  231.         {
  232.             p = conv_10( decimal_point, FALSE, &exponent_is_negative,
  233.                                                 &temp[ EXPONENT_LENGTH ], &t_len ) ;
  234.             *s++ = exponent_is_negative ? '-' : '+' ;
  235.             
  236.             /*
  237.              * Make sure the exponent has at least 2 digits
  238.              */
  239.             if ( t_len == 1 )
  240.                 *s++ = '0' ;
  241.             while ( t_len-- ) *s++ = *p++ ;
  242.         }
  243.         else
  244.         {
  245.             *s++ = '+' ;
  246.             *s++ = '0' ;
  247.             *s++ = '0' ;
  248.         }
  249.     }
  250.  
  251.     *len = s - buf ;
  252.     return( buf ) ;
  253. }
  254.  
  255.  
  256. /*
  257.  * Convert num to a base X number where X is a power of 2. nbits determines X.
  258.  * For example, if nbits is 3, we do base 8 conversion
  259.  * Return value:
  260.  *            a pointer to a string containing the number
  261.  *
  262.  * The caller provides a buffer for the string: that is the buf_end argument
  263.  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
  264.  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  265.  */
  266. PRIVATE char *conv_p2( num, nbits, format, buf_end, len )
  267.     register unsigned num ;
  268.     register int nbits ;
  269.     char format ;
  270.     char *buf_end ;
  271.     register int *len ;
  272. {
  273.     register int mask = ( 1 << nbits ) - 1 ;
  274.     register char *p = buf_end ;
  275.     static char low_digits[] = "0123456789abcdef" ;
  276.     static char upper_digits[] = "0123456789ABCDEF" ;
  277.     register char *digits = ( format == 'X' ) ? upper_digits : low_digits ;
  278.  
  279.     do
  280.     {
  281.         *--p = digits[ num & mask ] ;
  282.         num >>= nbits ;
  283.     }
  284.     while( num ) ;
  285.  
  286.     *len = buf_end - p ;
  287.     return( p ) ;
  288. }
  289.  
  290.  
  291.  
  292. /*
  293.  * Convert num to its decimal format.
  294.  * Return value:
  295.  *       - a pointer to a string containing the number (no sign)
  296.  *            - len contains the length of the string
  297.  *            - is_negative is set to TRUE or FALSE depending on the sign
  298.  *              of the number (always set to FALSE if is_unsigned is TRUE)
  299.  *
  300.  * The caller provides a buffer for the string: that is the buf_end argument
  301.  * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
  302.  * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
  303.  */
  304. PRIVATE char *conv_10( num, is_unsigned, is_negative, buf_end, len )
  305.     register int num ; 
  306.     register int is_unsigned ;
  307.     register int *is_negative ;
  308.     char *buf_end ;
  309.     register int *len ;
  310. {
  311.     register char *p = buf_end ;
  312.     register unsigned magnitude ;
  313.  
  314.     if ( is_unsigned )
  315.     {
  316.         magnitude = (unsigned) num ;
  317.         *is_negative = FALSE ;
  318.     }
  319.     else
  320.         if ( *is_negative = ( num < 0 ) )
  321.             if ( num != SMALLEST_INT )
  322.                 magnitude = (unsigned) -num ;
  323.             else
  324.             {
  325.                 register char *q ;
  326.                 char *str = S_SMALLEST_INT ;
  327.  
  328.                 for ( q = &str[ S_SMALLEST_INT_LEN - 1 ] ; q >= &str[ 0 ] ; q-- )
  329.                     *--p = *q ;
  330.                 *len = S_SMALLEST_INT_LEN ;
  331.                 return( p ) ;
  332.             }
  333.         else
  334.             magnitude = (unsigned) num ;
  335.  
  336.     do
  337.     {
  338.         register unsigned new_magnitude = magnitude / 10 ;
  339.  
  340.         *--p = magnitude - new_magnitude*10 + '0' ;
  341.         magnitude = new_magnitude ;
  342.     }
  343.     while ( magnitude ) ;
  344.     
  345.     *len = buf_end - p ;
  346.     return( p ) ;
  347. }
  348.  
  349.  
  350. /*
  351.  * Do format conversion placing the output in odp
  352.  */
  353. int __sio_converter( odp, fd, fmt, ap )
  354.     register __sio_od_t *odp ;
  355.     int fd ;
  356.     register char *fmt ;
  357.     va_list ap ;
  358. {
  359.     register char *sp ;
  360.     register char *bep ;
  361.     register int cc = 0 ;
  362.     register int i ;
  363.  
  364.     register char *s ;
  365.     char *q ;
  366.     int s_len ;
  367.  
  368.     register int min_width ;
  369.     int precision ;
  370.     enum { LEFT, RIGHT } adjust ;
  371.     char pad_char ;
  372.     char prefix_char ;
  373.  
  374.     double fp_num ;
  375.     unsigned i_num ;
  376.  
  377.     char num_buf[ NUM_BUF_SIZE ] ;
  378.     char char_buf[ 2 ] ;        /* for printing %% and %<unknown> */
  379.  
  380.     /*
  381.      * Flag variables
  382.      */
  383.     boolean_e is_long ;
  384.     boolean_e alternate_form ;
  385.     boolean_e print_sign ;
  386.     boolean_e print_blank ;
  387.     boolean_e adjust_precision ;
  388.     boolean_e adjust_width ;
  389.     int is_negative ;
  390.  
  391.     char *conv_10(), *conv_p2(), *conv_fp() ;
  392.     char *gcvt() ;
  393.     char *strchr() ;
  394.  
  395.  
  396.     sp = odp->nextb ;
  397.     bep = odp->buf_end ;
  398.  
  399.     while ( *fmt )
  400.     {
  401.         if ( *fmt != '%' )
  402.         {
  403.             INS_CHAR( *fmt, sp, bep, odp, cc, fd ) ;
  404.         }
  405.         else
  406.         {
  407.             /*
  408.              * Default variable settings
  409.              */
  410.             adjust = RIGHT ;
  411.             alternate_form = print_sign = print_blank = NO ;
  412.             pad_char = ' ' ;
  413.             prefix_char = NUL ;
  414.  
  415.             fmt++ ;
  416.  
  417.             /*
  418.              * Try to avoid checking for flags, width or precision
  419.              */
  420.             if ( isascii( *fmt ) && ! islower( *fmt ) )
  421.             {
  422.                 /*
  423.                  * Recognize flags: -, #, BLANK, +
  424.                  */
  425.                 for ( ;; fmt++ )
  426.                 {
  427.                     if ( *fmt == '-' )
  428.                         adjust = LEFT ;
  429.                     else if ( *fmt == '+' )
  430.                         print_sign = YES ;
  431.                     else if ( *fmt == '#' )
  432.                         alternate_form = YES ;
  433.                     else if ( *fmt == ' ' )
  434.                         print_blank = YES ;
  435.                     else if ( *fmt == '0' )
  436.                         pad_char = '0' ;
  437.                     else
  438.                         break ;
  439.                 }
  440.  
  441.                 /*
  442.                  * Check if a width was specified
  443.                  */
  444.                 if ( isdigit( *fmt ) )
  445.                 {
  446.                     STR_TO_DEC( fmt, min_width ) ;
  447.                     adjust_width = YES ;
  448.                 }
  449.                 else if ( *fmt == '*' )
  450.                 {
  451.                     min_width = va_arg( ap, int ) ;
  452.                     fmt++ ;
  453.                     adjust_width = YES ;
  454.                     if ( min_width < 0 )
  455.                     {
  456.                         adjust = LEFT ;
  457.                         min_width = -min_width ;
  458.                     }
  459.                 }
  460.                 else
  461.                     adjust_width = NO ;
  462.                 
  463.                 /*
  464.                  * Check if a precision was specified
  465.                  */
  466.                 if ( *fmt == '.' )
  467.                 {
  468.                     adjust_precision = YES ;
  469.                     fmt++ ;
  470.                     if ( isdigit( *fmt ) )
  471.                     {
  472.                         STR_TO_DEC( fmt, precision ) ;
  473.                     }
  474.                     else if ( *fmt == '*' )
  475.                     {
  476.                         precision = va_arg( ap, int ) ;
  477.                         fmt++ ;
  478.                         if ( precision < 0 )
  479.                             precision = 0 ;
  480.                     }
  481.                     else
  482.                         precision = 0 ;
  483.                 }
  484.                 else
  485.                     adjust_precision = NO ;
  486.             }
  487.             else
  488.                 adjust_precision = adjust_width = NO ;
  489.  
  490.             /*
  491.              * Modifier check
  492.              */
  493.             if ( *fmt == 'l' )
  494.             {
  495.                 is_long = YES ;
  496.                 fmt++ ;
  497.             }
  498.             else
  499.                 is_long = NO ;
  500.  
  501.             /*
  502.              * Argument extraction and printing.
  503.              * First we determine the argument type.
  504.              * Then, we convert the argument to a string.
  505.              * On exit from the switch, s points to the string that
  506.              * must be printed, s_len has the length of the string
  507.              * The precision requirements, if any, are reflected in s_len.
  508.              *
  509.              * NOTE: pad_char may be set to '0' because of the 0 flag.
  510.              *            It is reset to ' ' by non-numeric formats
  511.              */
  512.             switch( *fmt )
  513.             {
  514.                 case 'd':
  515.                 case 'i':
  516.                 case 'u':
  517. #ifdef LONG_IS_BIGGER
  518.                     if ( is_long )
  519.                         /* CALL APPROPRIATE FUNCTION */
  520.                     else
  521. #endif
  522.                         s = conv_10( va_arg( ap, int ), (*fmt) == 'u', &is_negative,
  523.                                                 &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  524.                     FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  525.  
  526.                     if ( *fmt != 'u' )
  527.                     {
  528.                         if ( is_negative )
  529.                             prefix_char = '-' ;
  530.                         else if ( print_sign )
  531.                             prefix_char = '+' ;
  532.                         else if ( print_blank )
  533.                             prefix_char = ' ' ;
  534.                     }
  535.                     break ;
  536.                 
  537.  
  538.                 case 'o':
  539. #ifdef LONG_IS_BIGGER
  540.                     if ( is_long )
  541.                         /* CALL APPROPRIATE FUNCTION */
  542.                     else
  543. #endif
  544.                         s = conv_p2( va_arg( ap, unsigned ), 3, *fmt, 
  545.                                                 &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  546.                     FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  547.                     if ( alternate_form && *s != '0' )
  548.                     {
  549.                         *--s = '0' ;
  550.                         s_len++ ;
  551.                     }
  552.                     break ;
  553.                 
  554.  
  555.                 case 'x':
  556.                 case 'X':
  557. #ifdef LONG_IS_BIGGER
  558.                     if ( is_long )
  559.                         /* CALL APPROPRIATE FUNCTION */
  560.                     else
  561. #endif
  562.                         s = conv_p2( i_num = va_arg( ap, unsigned ), 4, *fmt,
  563.                                                 &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  564.                     FIX_PRECISION( adjust_precision, precision, s, s_len ) ;
  565.                     if ( alternate_form && i_num != 0 )
  566.                     {
  567.                         *--s = *fmt ;            /* 'x' or 'X' */
  568.                         *--s = '0' ;
  569.                         s_len += 2 ;
  570.                     }
  571.                     break ;
  572.                 
  573.  
  574.                 case 's':
  575.                     s = va_arg( ap, char * ) ;
  576.                     if ( s != NULL )
  577.                     {
  578.                         s_len = strlen( s ) ;
  579.                         if ( adjust_precision && precision < s_len )
  580.                             s_len = precision ;
  581.                     }
  582.                     else
  583.                     {
  584.                         s = S_NULL ;
  585.                         s_len = S_NULL_LEN ;
  586.                     }
  587.                     pad_char = ' ' ;
  588.                     break ;
  589.                 
  590.  
  591.                 case 'f':
  592.                 case 'e':
  593.                 case 'E':
  594.                     fp_num = va_arg( ap, double ) ;
  595.  
  596.                     s = conv_fp( *fmt, fp_num, alternate_form,
  597.                             ( adjust_precision == NO ) ? FLOAT_DIGITS : precision,
  598.                                                     &is_negative, &num_buf[ 1 ], &s_len ) ;
  599.                     if ( is_negative )
  600.                         prefix_char = '-' ;
  601.                     else if ( print_sign )
  602.                         prefix_char = '+' ;
  603.                     else if ( print_blank )
  604.                         prefix_char = ' ' ;
  605.                     break ;
  606.  
  607.  
  608.                 case 'g':
  609.                 case 'G':
  610.                     if ( adjust_precision == NO )
  611.                         precision = FLOAT_DIGITS ;
  612.                     else if ( precision == 0 )
  613.                         precision = 1 ;
  614.                     /*
  615.                      * We use &num_buf[ 1 ], so that we have room for the sign
  616.                      */
  617.                     s = gcvt( va_arg( ap, double ), precision, &num_buf[ 1 ] ) ;
  618.                     if ( *s == '-' )
  619.                         prefix_char = *s++ ;
  620.                     else if ( print_sign )
  621.                         prefix_char = '+' ;
  622.                     else if ( print_blank )
  623.                         prefix_char = ' ' ;
  624.  
  625.                     s_len = strlen( s ) ;
  626.  
  627.                     if ( alternate_form && ( q = strchr( s, '.' ) ) == NULL )
  628.                         s[ s_len++ ] = '.' ;
  629.                     if ( *fmt == 'G' && ( q = strchr( s, 'e' ) ) != NULL )
  630.                         *q = 'E' ;
  631.                     break ;
  632.  
  633.  
  634.                 case 'c':
  635.                     char_buf[ 0 ] = (char) (va_arg( ap, int )) ;
  636.                     s = &char_buf[ 0 ] ;
  637.                     s_len = 1 ;
  638.                     pad_char = ' ' ;
  639.                     break ;
  640.  
  641.  
  642.                 case '%':
  643.                     char_buf[ 0 ] = '%' ;
  644.                     s = &char_buf[ 0 ] ;
  645.                     s_len = 1 ;
  646.                     pad_char = ' ' ;
  647.                     break ;
  648.  
  649.  
  650.                 case 'n':
  651.                     *(va_arg( ap, int * )) = cc ;
  652.                     break ;
  653.  
  654.                 /*
  655.                  * Always extract the argument as a "char *" pointer. We 
  656.                  * should be using "void *" but there are still machines 
  657.                  * that don't understand it.
  658.                  * If the pointer size is equal to the size of an unsigned
  659.                  * integer we convert the pointer to a hex number, otherwise 
  660.                  * we print "%p" to indicate that we don't handle "%p".
  661.                  */
  662.                 case 'p':
  663.                     {
  664.                         char *pointer  = va_arg( ap, char *) ;
  665.  
  666.                         if ( sizeof( char * ) <= sizeof( unsigned ) )
  667.                             s = conv_p2( (unsigned ) pointer, 4, 'x', 
  668.                                                     &num_buf[ NUM_BUF_SIZE ], &s_len ) ;
  669.                         else
  670.                         {
  671.                             s = "%p" ;
  672.                             s_len = 2 ;
  673.                         }
  674.                     }
  675.                     pad_char = ' ' ;
  676.                     break ;
  677.                     
  678.  
  679.                 case NUL:
  680.                     /*
  681.                      * The last character of the format string was %.
  682.                      * We ignore it.
  683.                      */
  684.                     continue ;
  685.  
  686.  
  687.                     /*
  688.                       * The default case is for unrecognized %'s.
  689.                      * We print %<char> to help the user identify what
  690.                      * option is not understood.
  691.                      * This is also useful in case the user wants to pass
  692.                      * the output of __sio_converter to another function
  693.                      * that understands some other %<char> (like syslog).
  694.                      */
  695.                 default:
  696.                     char_buf[ 0 ] = '%' ;
  697.                     char_buf[ 1 ] = *fmt ;
  698.                     s = char_buf ;
  699.                     s_len = 2 ;
  700.                     pad_char = ' ' ;
  701.                     break ;
  702.             }
  703.  
  704.             if ( prefix_char != NUL )
  705.             {
  706.                 *--s = prefix_char ;
  707.                 s_len++ ;
  708.             }
  709.  
  710.             if ( adjust_width && adjust == RIGHT && min_width > s_len )
  711.             {
  712.                 if ( pad_char == '0' && prefix_char != NUL )
  713.                 {
  714.                     INS_CHAR( *s, sp, bep, odp, cc, fd )
  715.                     s++ ;
  716.                     s_len-- ;
  717.                     min_width-- ;
  718.                 }
  719.                 PAD( min_width, s_len, pad_char ) ;
  720.             }
  721.  
  722.             /*
  723.              * Print the string s. 
  724.              */
  725.             for ( i = s_len ; i != 0 ; i-- )
  726.             {
  727.                 INS_CHAR( *s, sp, bep, odp, cc, fd ) ;
  728.                 s++ ;
  729.             }
  730.  
  731.             if ( adjust_width && adjust == LEFT && min_width > s_len )
  732.                 PAD( min_width, s_len, pad_char ) ;
  733.         }
  734.         fmt++ ;
  735.     }
  736.     odp->nextb = sp ;
  737.     return( cc ) ;
  738. }
  739.